import os, re, shutil, sys

class DirStack:
    def __init__(self):
        self._stack = []

    def pushd(self,path):
        self._stack.append(os.getcwd())
        os.chdir(path)

    def popd(self):
        if not self._stack:
            raise IOError, 'Directory stack is empty'
        os.chdir(self._stack.pop())


def substitute(file_src, file_dst, replaces):
    content = open(file_src, 'r').read()

    for old, new in replaces.items():
        try:
            content = content.replace(old, new)
        except:
            raise Exception, 'Error while substituting %s => %s' % (old, new)

    f = open(file_dst, 'w')
    f.write(content)
    f.close()

def any_match(s, patterns):
    for pattern in patterns:
        if pattern.match(s): return True
    return False

def precompile(lst):
    #return [re.compile('^(%s)$' % pattern.replace('*', '.*')) for pattern in lst if pattern]
    return [re.compile('^(%s)$' % pattern) for pattern in lst if pattern]

def unixpath(s):
    return s.replace('\\', '/')

def _forcelist(var):
    if not var:
        return ()
    elif isinstance(var, basestring):
        return (var,)
    else:
        return var

def filelist(start, skipfiles=None, skippathes=None):
    if not os.path.exists(start):
        raise Exception, "`%s` does not exists" % start

    res = []
    skipfiles = precompile(_forcelist(skipfiles))
    skippathes = precompile(_forcelist(skippathes))

    for dirpath, dirnames, filenames in os.walk(start):
        # skip
        for dirname in dirnames[:]:
            if any_match(dirname, skipfiles):
                dirnames.remove(dirname)
            if os.path.islink(os.path.join(dirpath, dirname)):
                filenames.append(dirname)

        # adding dir
        unix_dirpath = unixpath(dirpath)
        if not any_match(unix_dirpath, skippathes):
            res.append(unix_dirpath)

        # adding files
        for file in filenames:
            if not any_match(file, skipfiles):
                unix_filepath = unixpath(os.path.join(dirpath, file))
                if not any_match(unix_filepath, skippathes):
                    res.append(unix_filepath)

    try:
        res.remove(start)
    except:
        print 'start',
        raise
    return res

def checkexists(files):
    not_exists = [f for f in files if not os.path.exists(f)]
    if not_exists:
        print 'Need files:\n%s\n' % '\n'.join(not_exists)
        sys.exit()
